<template>
  <div class="SubjectForm">
    <JsonForm
      ref="$jsonForm"
      v-model:isRender="isRender"
      :is-result="isResult"
      label="测试科目设计"
      :schemas="schemas"
      json-label="测试评估"
      @options-load="onOptionsLoad"
    />
    <Teleport v-if="isMounted" to="#step-control">
      <div class="my-btn-group mt-32">
        <n-button @click="emits('prev')">上一步</n-button>
        <n-button :color="appStore.buttonColor" @click="handleNext">
          {{ step === 4 ? '创建测试' : '下一步' }}
        </n-button>
      </div>
    </Teleport>
  </div>
</template>
<script setup lang="jsx">
import { useAppStore } from '@/store'
import { useMounted } from '@/hooks/useMounted'
import * as testRecordApi from '@/api/testRecord'
import * as testObjectApi from '@/api/testObject'
import * as dataSetApi from '@/api/dataSet'
import { cloneDeep } from 'lodash-es'
import { notEvaluateSimulatorValues, specialSimulatorEnum } from '@/enum/simulator'
defineOptions({
  name: 'SubjectForm',
})
const appStore = useAppStore()
const emits = defineEmits(['next', 'prev', 'create', 'isEvaluate'])
const props = defineProps({
  initData: {
    type: Object,
    default: null,
  },
  step: {
    type: Number,
    default: 1,
  },
  importJsonData: {
    type: Object,
    default: null,
  },
})
const { isMounted } = useMounted()

const $jsonForm = ref(null)

function getObjectList() {
  return testObjectApi.listAll()
}
function getMetaTaskTypeList() {
  return testObjectApi.metaTaskTypeList()
}
function getModeList() {
  return testObjectApi.modeList()
}
function getScenarioList() {
  return testObjectApi.scenarioList()
}
function getSubjectList(_, __, params) {
  return testObjectApi.subjectList(params)
}
function getDataSetList(_, __, params) {
  return dataSetApi.listAll(params)
}
function getEmulatorList(_, __, params) {
  return testObjectApi.emulatorList(params)
}
function getMethodsList(_, __, params) {
  return testObjectApi.methodsList(params)
}
function getTestIndicatorList(params) {
  return testObjectApi.testIndicatorList(params)
}
function getEvaluateIndicatorList(params) {
  return testObjectApi.evaluateIndicator(params)
}
function getEvaluationModelList(_, __, params) {
  const { evaluationIndicatorCollection, testIndicatorCollection } = $jsonForm.value.format(
    'json',
    params
  )
  return testObjectApi.evaluationModelList({
    evalMetricNames: evaluationIndicatorCollection?.length
      ? evaluationIndicatorCollection.join(',')
      : '',
    testMetricNames: testIndicatorCollection?.length ? testIndicatorCollection.join(',') : '',
  })
}
const testTypeOptions = ref([
  { label: '算法测试', value: '1' },
  { label: '人工测试', value: '2' },
])
const visualizationOptions = ref([
  { label: '是', value: '1' },
  { label: '否', value: '0' },
])
const testTypeSceneOptions = ref([
  { label: '场景_1', value: '1' },
  { label: '场景_2', value: '2' },
  { label: '场景_3', value: '3' },
])
const isResult = computed(() => props.step >= 4)
const isRender = ref(false)
/**
 * enableFormat 代表数据是同步获取还是异步获取
 * 同步将直接读取componentProps-options
 * 异步由组件自动触发监听获取
 */
const schemas = computed(() => {
  // console.log('redender')
  if (!props.initData) return []
  const data = cloneDeep(props.initData)
  return [
    {
      groupLabel: '测试',
      isShow: ({ isResult }) => !isResult,
    },
    {
      field: 'testObjectId',
      label: '被测对象名称',
      component: 'AsyncSelect',
      componentProps: {
        defaultValue: data.testObjectId ?? null,
        options: getObjectList,
        labelKey: 'name',
        valueKey: 'id',
        disabled: true,
      },
      isShow: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'objectViewName',
      label: data.tagName === '算法' ? '对象类型' : '对象类型+标签1',
      component: 'NInput',
      componentProps: {
        defaultValue:
          data.tagName === '算法'
            ? data.testObjectTypeName
            : `${data.testObjectTypeName}(${data.tagName})`,
        disabled: true,
      },
      isShow: ({ isResult }) => isResult,
    },
    {
      field: 'metaMissionType',
      label: '元任务类型',
      component: 'AsyncSelect',
      componentProps: {
        defaultValue: data.metaMissionType ?? null,
        options: getMetaTaskTypeList,
        labelKey: 'metaTaskName',
        valueKey: 'id',
        disabled: true,
      },
      enableFormat: 'async',
    },
    {
      field: 'testModeId',
      label: '测试模式',
      component: 'AsyncSelect',
      componentProps: {
        defaultValue: data.testModeId ?? null,
        options: getModeList,
        labelKey: 'testModeName',
        valueKey: 'id',
        disabled: true,
      },
      isShow: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'testScene',
      label: '测试场景',
      component: 'AsyncSelect',
      rule: [{ required: true, message: '请选择测试场景' }],
      componentProps: {
        defaultValue: data.testScene ?? null,
        options: getScenarioList,
        labelKey: 'testScenarioName',
        valueKey: 'id',
      },
      isDisabled: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'testSubjectIds',
      label: '测试科目名称',
      component: 'AsyncSelect',
      rule: [{ required: true, message: '请选择测试科目名称' }],
      componentProps: {
        defaultValue: data.testSubjectIds ?? null,
        options: getSubjectList,
        labelKey: 'subjectsName',
        valueKey: 'id',
        getExtraParams(form) {
          return {
            metaTaskTypeId: form.metaMissionType,
            scenarioId: form.testScene,
          }
        },
        onChangeExtraParams() {
          isRender.value && $jsonForm.value.setFormData({ testSubjectIds: null })
        },
      },
      isDisabled: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'datasetIds',
      label: '基准数据集',
      component: 'AsyncSelect',
      rule: [{ required: true, message: '请选择基准数据集' }],
      componentProps: {
        defaultValue: data.datasetIds ?? null,
        options: getDataSetList,
        labelKey: 'datasetName',
        valueKey: 'id',
        getExtraParams(form) {
          return {
            metaTaskTypeId: form.metaMissionType,
          }
        },
        onChangeExtraParams() {
          isRender.value && $jsonForm.value.setFormData({ datasetIds: null })
        },
      },
      isDisabled: ({ isResult }) => isResult,
      isShow: () => data.testModeId === '2',
      enableFormat: 'async',
    },
    {
      field: 'simulator',
      label: '仿真器选择',
      component: 'AsyncSelect',
      rule: [{ required: true, message: '请选择仿真器' }],
      componentProps: {
        defaultValue: data.simulator ?? null,
        options: getEmulatorList,
        labelKey: 'emulatorName',
        valueKey: 'id',
        onUpdateValue(e) {
          // 启明星
          if (notEvaluateSimulatorValues.includes(e)) {
            $message.warning(`当前仿真器不支持评估!`)
            emits('isEvaluate', false)
          } else {
            emits('isEvaluate', true)
          }
          $jsonForm.value.setFormData({
            testTypeScene: '1',
            simulatorTotalduration: null,
            simulatorStepping: null,
          })
        },
        getExtraParams(form) {
          return {
            subjectIds: form.testSubjectIds ? [form.testSubjectIds] : [],
            testModeId: data.testModeId,
            metaTaskTypeId: form.metaMissionType,
            scenarioId: form.testScene,
          }
        },
        onChangeExtraParams() {
          if (isRender.value) {
            $jsonForm.value.setFormData({ simulator: null })
            emits('isEvaluate', true)
          }
        },
      },
      isDisabled: ({ isResult }) => isResult,
      isShow: () => data.testModeId === '1',
      enableFormat: 'async',
    },
    {
      field: 'testMethodId',
      label: '测试方法',
      component: 'AsyncSelect',
      rule: [{ required: true, message: '请选择测试方法' }],
      componentProps: {
        defaultValue: data.testMethodId ?? null,
        options: getMethodsList,
        labelKey: 'testMethodName',
        valueKey: 'id',
        getExtraParams(form) {
          return {
            subjectIds: form.testSubjectIds ? [form.testSubjectIds] : [],
            testModeId: data.testModeId,
            metaTaskTypeId: form.metaMissionType,
            scenarioId: form.testScene,
          }
        },
        onChangeExtraParams() {
          isRender.value && $jsonForm.value.setFormData({ testMethodId: null })
        },
      },
      isDisabled: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'testTypeId',
      label: '测试类型',
      component: 'NRadioGroup',
      rule: [{ required: true, message: '请选择测试类型' }],
      componentProps: {
        defaultValue: data.testTypeId ?? '1',
        options: testTypeOptions.value,
        onUpdateValue(e) {
          if (e === '2') {
            // 人工测试时可视化只能为-是
            $jsonForm.value.setFormData({ visualization: '1' })
          }
        },
      },

      isDisabled: ({ isResult }) => isResult,
      enableFormat: 'sync',
    },
    {
      field: 'visualization',
      label: '可视化支持',
      component: 'NRadioGroup',
      rule: [{ required: true, message: '请选择可视化支持' }],
      componentProps: {
        defaultValue: data.visualization ?? '0',
        options: visualizationOptions.value,
      },
      generateOptions: ({ formData }) =>
        formData.testTypeId === '2' ? [visualizationOptions.value[0]] : visualizationOptions.value,
      isDisabled: ({ isResult }) => isResult,
      isShow: () => data.testModeId === '1',
      enableFormat: 'sync',
    },
    {
      field: 'testTypeScene',
      label: '测试场景类型',
      component: 'NRadioGroup',
      rule: [{ required: true, message: '请输入测试场景类型' }],
      componentProps: {
        defaultValue: '1',
        options: testTypeSceneOptions.value,
      },
      isDisabled: ({ isResult }) => isResult,
      isShow: ({ formData }) => formData.simulator === specialSimulatorEnum.QT,
      enableFormat: 'sync',
    },
    {
      field: 'simulatorTotalduration',
      label: '仿真总时间(s)',
      component: 'NInputNumber',
      rule: [{ required: true, message: '请输入仿真总时间' }],
      componentProps: {
        defaultValue: null,
        min: 0,
      },
      isDisabled: ({ isResult }) => isResult,
      isShow: ({ formData }) => formData.simulator === specialSimulatorEnum.QT,
    },
    {
      field: 'simulatorStepping',
      label: '仿真步进(s)',
      component: 'NInputNumber',
      rule: [{ required: true, message: '请选择仿真步进' }],
      componentProps: {
        defaultValue: null,
        min: 0,
      },
      isDisabled: ({ isResult }) => isResult,
      isShow: ({ formData }) => formData.simulator === specialSimulatorEnum.QT,
    },
    {
      field: 'testIndicatorCollection',
      label: '测试指标',
      component: 'MyTags',
      rule: [{ required: true, message: '请选择测试指标' }],
      componentProps: {
        defaultValue: data.testIndicatorCollection ?? [],
        options: getTestIndicatorList,
        labelKey: 'testIndicatorName',
        valueKey: 'id',
        multiple: true,
        autoSelectAll: true,
        getExtraParams(form) {
          return {
            subjectIds: form.testSubjectIds ? [form.testSubjectIds] : [],
            testModeId: data.testModeId,
            metaTaskTypeId: form.metaMissionType,
            scenarioId: form.testScene,
            testMethodId: form.testMethodId,
          }
        },
        onChangeExtraParams() {
          isRender.value && $jsonForm.value.setFormData({ testIndicatorCollection: [] })
        },
      },
      isDisabled: ({ isResult }) => isResult,
      isOnlySelect: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'evaluationIndicatorCollection',
      label: '评估指标',
      component: 'MyTags',
      rule: [{ required: true, message: '请选择评估指标' }],
      componentProps: {
        defaultValue: data.evaluationIndicatorCollection ?? [],
        options: getEvaluateIndicatorList,
        labelKey: 'estimateIndicatorName',
        valueKey: 'id',
        multiple: true,
        autoSelectAll: true,
        getExtraParams(form) {
          return {
            subjectIds: form.testSubjectIds ? [form.testSubjectIds] : [],
            testModeId: data.testModeId,
            metaTaskTypeId: form.metaMissionType,
            scenarioId: form.testScene,
            testMethodId: form.testMethodId,
          }
        },
        onChangeExtraParams() {
          isRender.value && $jsonForm.value.setFormData({ evaluationIndicatorCollection: [] })
        },
      },
      isDisabled: ({ isResult }) => isResult,
      isOnlySelect: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      groupLabel: '评估',
      isShow: ({ isResult }) => !isResult,
    },
    {
      field: 'evaluationMode',
      label: '评估模型',
      component: 'AsyncSelect',
      // rule: [{ required: true, message: '请选择评估模型' }],
      componentProps: {
        defaultValue: data.evaluationMode ?? null,
        options: getEvaluationModelList,
        labelKey: 'name',
        valueKey: 'id',
        // autoInitOptions: isResult.value,
        changeWait: 600,
        getExtraParams(form) {
          return {
            evaluationIndicatorCollection: form.evaluationIndicatorCollection,
            testIndicatorCollection: form.testIndicatorCollection,
          }
        },
        onChangeExtraParams() {
          isRender.value && $jsonForm.value.setFormData({ evaluationMode: null })
        },
        onUpdateValue(_, item) {
          $jsonForm.value.setFormData({
            evaluationModeParameters: JSON.stringify(item?.paraList || []),
          })
        },
      },
      isDisabled: ({ isResult }) => isResult,
      enableFormat: 'async',
    },
    {
      field: 'evaluationModeParameters',
      label: '评估模型参数',
      component: 'NInput',
      // rule: [{ required: true, message: '请选择评估模型参数' }],
      componentProps: {
        defaultValue: data.evaluationModeParameters ?? null,
        type: 'textarea',
        autosize: {
          minRows: 3,
        },
      },
      isDisabled: ({ isResult }) => isResult,
    },
  ]
})

function onOptionsLoad() {
  if (props.importJsonData) {
    $jsonForm?.value?.setJsonData(props.importJsonData)
  }
}

function handleNext() {
  $jsonForm?.value?.validateForm((data, json) => {
    if (props.step === 3) {
      emits('next')
    } else if (props.step === 4) {
      let testName = `${json.testSubjectIds}-${json.testObjectId}-${Date.now()}`
      testRecordApi
        .add({ ...data, testName })
        .then((res) => {
          $message.success('创建测试成功!')
          //获取id启动
          emits('create', res.data.testId)
          emits('next')
        })
        .catch((err) => {
          console.log(err)
          $message.error('创建测试失败!')
        })
    }
  })
}
</script>
<style lang="scss" scoped></style>
